package com.demo.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.demo.entity.QualityControlDatePO;
import com.demo.enums.*;
import com.demo.mapper.*;
import com.demo.response.Result;
import com.demo.service.QualityControlService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 质控服务实现类
 */
@Service
@Slf4j
public class QualityControlServiceImp implements QualityControlService {
    @Resource
    VtePreventiveMapper vtePreventiveMapper;
    @Resource
    DepartmentMapper departmentMapper;
    @Resource
    DischargeSummaryMapper summaryMapper;
    @Resource
    PatientTransitionMapper patientTransitionMapper;
    @Resource
    VtePreventiveDoctorAdviceMapper doctorAdviceMapper;
    @Resource
    DvtDiagnoseMapper dvtDiagnoseMapper;

    DecimalFormat df = new DecimalFormat("0.##");

    /**
     * 风险评估实施指标---VTE风险评估率
     *
     * 基本公式
     * 统计时间段内进行VTE风险评估的患者人数/统计时间段内入院人数
     *
     * 全部
     * 	统计时间段：月度（当月初第一天00:00:00~当月末最后一天23:59:59）；季度（季度初第一天00:00:00~季度末最后一天23:59:59）；年度（年初第一天00:00:00~年末最后一天23:59:59）【下同】
     * 	分子：初始评估签字时间在统计时间段内，选择的病区（评估病区，无论患者是否转出病区）评估的新入或转入（除外原有病人的评估）患者人数（如果评估多次，计一次）
     * 	分母：统计时间段内，新入和转入到选择病区的人数（如果多次新入或转入同一病区，计一次）。
     *
     * 入科
     * 	分子：初始评估签字时间在统计时间段内，选择的病区（评估病区，无论患者是否转出病区）进行风险评估时机为入科的患者人数（如果评估多次，计一次）
     *
     * 术后
     * 	分子：初始评估签字时间在统计时间段内，选择的病区（评估病区，无论患者是否转出病区）进行风险评估时机为术后的患者人数（如果评估多次，计一次）
     *
     * 分娩
     * 	分子：初始评估签字时间在统计时间段内，选择的病区（评估病区，无论患者是否转出病区）进行风险评估时机为分娩的患者人数（如果评估多次，计一次）
     *
     * 变化
     * 	分子：初始评估签字时间在统计时间段内，选择的病区（评估病区，无论患者是否转出病区）进行风险评估时机为变化的患者人数（如果评估多次，计一次）
     *
     * 定期
     * 	分子：初始评估签字时间在统计时间段内，选择的病区（评估病区，无论患者是否转出病区）进行风险评估时机为定期的患者人数（如果评估多次，计一次）
     *
     * 出院
     * 	分子：初始评估签字时间在统计时间段内，选择的病区（评估病区，无论患者是否转出病区）进行风险评估时机为出院的患者人数（如果评估多次，计一次）
     *
     * @param deptSn    科室/病区ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeType  时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result riskVteAssesProbability(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 所有病人
            Integer patientCount = patientTransitionMapper.getDurationPatientSum(departments, item.getStartTime(), item.getEndTime());
            if (patientCount == null) {
                patientCount = 0;
            }
            // 全部
            Integer allVteSum = vtePreventiveMapper.getSumByVtePreventiveFlow(departments, item.getStartTime(), item.getEndTime(), PreventiveDiagnoseOpportunityEnum.ALL.getValue());
            if (allVteSum == null) {
                allVteSum = 0;
            }
            // 新入
            Integer hospitalizedSum = vtePreventiveMapper.getSumByVtePreventiveFlow(departments, item.getStartTime(), item.getEndTime(), PreventiveDiagnoseOpportunityEnum.XIN_RU.getValue()).intValue();
            if (hospitalizedSum == null) {
                hospitalizedSum = 0;
            }
            // 术后
            Integer postOperationSum = vtePreventiveMapper.getSumByVtePreventiveFlow(departments, item.getStartTime(), item.getEndTime(), PreventiveDiagnoseOpportunityEnum.SHU_HOU.getValue()).intValue();
            if (postOperationSum == null) {
                postOperationSum = 0;
            }
            // 分娩
            Integer deliverySum = vtePreventiveMapper.getSumByVtePreventiveFlow(departments, item.getStartTime(), item.getEndTime(), PreventiveDiagnoseOpportunityEnum.FEN_MIAN.getValue()).intValue();
            if (deliverySum == null) {
                deliverySum = 0;
            }
            // 变化
            Integer variationSum = vtePreventiveMapper.getSumByVtePreventiveFlow(departments, item.getStartTime(), item.getEndTime(), PreventiveDiagnoseOpportunityEnum.BING_QING_BIAN_HUA.getValue()).intValue();
            if (variationSum == null) {
                variationSum = 0;
            }
            // 出院
            Integer leaveHospitalSum = vtePreventiveMapper.getSumByVtePreventiveFlow(departments, item.getStartTime(), item.getEndTime(), PreventiveDiagnoseOpportunityEnum.CHU_YUAN.getValue()).intValue();
            if (leaveHospitalSum == null) {
                leaveHospitalSum = 0;
            }
            // 定期
            Integer regularSum = vtePreventiveMapper.getSumByVtePreventiveFlow(departments, item.getStartTime(), item.getEndTime(), PreventiveDiagnoseOpportunityEnum.DING_QI.getValue()).intValue();
            if (regularSum == null) {
                regularSum = 0;
            }
            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allVte", patientCount == 0 ? "0%" : df.format((allVteSum * 100.0F / patientCount)) + "%");
            report.put("hospitalized", patientCount == 0 ? "0%" : df.format((hospitalizedSum * 100.0F / patientCount)) + "%");
            report.put("postoperation", patientCount == 0 ? "0%" : df.format((postOperationSum * 100.0F / patientCount)) + "%");
            report.put("delivery", patientCount == 0 ? "0%" : df.format((deliverySum * 100.0F / patientCount)) + "%");
            report.put("variation", patientCount == 0 ? "0%" : df.format((variationSum * 100.0F / patientCount)) + "%");
            report.put("leaveHospital", patientCount == 0 ? "0%" : df.format((leaveHospitalSum * 100.0F / patientCount)) + "%");
            report.put("regular", patientCount == 0 ? "0%" : df.format((regularSum * 100.0F / patientCount)) + "%");
            report.put("patientCount", Convert.toStr(patientCount));
            report.put("allVteSum", Convert.toStr(allVteSum));
            report.put("hospitalizedSum", Convert.toStr(hospitalizedSum));
            report.put("postoperationSum", Convert.toStr(postOperationSum));
            report.put("deliverySum", Convert.toStr(deliverySum));
            report.put("variationSum", Convert.toStr(variationSum));
            report.put("leaveHospitalSum", Convert.toStr(leaveHospitalSum));
            report.put("regularSum", Convert.toStr(regularSum));
            list.add(report);
        }
        return Result.success(list);
    }

    /**
     * 风险评估实施指标---VTE中高危患者出血风险评估率
     *
     * 基本公式
     * 统计时间段内进行禁忌评估且危险分层为中高危的次数 / 统计时间段内进行VTE风险评估且危险分层为中高危的次数
     *
     * 全部
     * 	分子：禁忌评估（复核）签字时间在统计时间段内且危险分层为中高危，选择的病区（评估病区，无论患者是否转出病区）内的评估次数（如果评估多次，计多次）
     * 	分母：初次评估签字时间在统计时间段内且危险分层为中高危，选择病区（评估病区，无论患者是否转出病区）内的评估次数（如果评估为多次，计多次）。
     *
     * 中危
     * 	分子：禁忌评估（复核）签字时间在统计时间段内且危险分层为中危，选择的病区（评估病区，无论患者是否转出病区）内的评估次数（如果评估多次，计多次）
     * 	分母：初次评估签字时间在统计时间段内且危险分层为中危，选择病区（评估病区，无论患者是否转出病区）内的评估次数（如果评估为多次，计多次）。
     *
     * 高危
     * 	分子：禁忌评估（复核）签字时间在统计时间段内且危险分层为高危，选择的病区（评估病区，无论患者是否转出病区）内的评估次数（如果评估多次，计多次）
     * 	分母：初次评估签字时间在统计时间段内且危险分层为高危，选择病区（评估病区，无论患者是否转出病区）内的评估次数（如果评估为多次，计多次）。
     *
     * @param deptSn    科室/病区ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeType  时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result riskVteCrowningPatient(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        Integer[] middleHigh = {2, 3};// 高危，中危
        Integer[] middle = {3};// 中危
        Integer[] highRank = {2};// 高危
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 全部(中高危)
            int sumMiddleHigh = vtePreventiveMapper.getSumByVtePreventiveConfirm(departments, middleHigh, item.getStartTime(), item.getEndTime()).intValue();
            int sumMiddleHighTboo = vtePreventiveMapper.getSumByVtePreventiveSign(departments, middleHigh, item.getStartTime(), item.getEndTime()).intValue();
            // 中危
            int sumMiddle = vtePreventiveMapper.getSumByVtePreventiveConfirm(departments, middle, item.getStartTime(), item.getEndTime()).intValue();
            int sumMiddleTboo = vtePreventiveMapper.getSumByVtePreventiveSign(departments, middle, item.getStartTime(), item.getEndTime()).intValue();
            // 高危
            int sumHigh = vtePreventiveMapper.getSumByVtePreventiveConfirm(departments, highRank, item.getStartTime(), item.getEndTime()).intValue();
            int sumHighTboo = vtePreventiveMapper.getSumByVtePreventiveSign(departments, highRank, item.getStartTime(), item.getEndTime()).intValue();
            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allVtePatient", sumMiddleHigh == 0 ? "0%" : df.format((sumMiddleHighTboo * 100.0F / sumMiddleHigh)) + "%");
            report.put("middle", sumMiddle == 0 ? "0%" : df.format((sumMiddleTboo * 100.0F / sumMiddle)) + "%");
            report.put("height", sumHigh == 0 ? "0%" : df.format((sumHighTboo * 100.0F / sumHigh)) + "%");
            report.put("sumMiddleHighTboo", Convert.toStr(sumMiddleHighTboo));
            report.put("sumMiddleHigh", Convert.toStr(sumMiddleHigh));
            report.put("sumMiddleTboo", Convert.toStr(sumMiddleTboo));
            report.put("sumMiddle", Convert.toStr(sumMiddle));
            report.put("sumHighTboo", Convert.toStr(sumHighTboo));
            report.put("sumHigh", Convert.toStr(sumHigh));
            list.add(report);
        }
        return Result.success(list);
    }

    /**
     * 风险评估实施指标---VTE风险出院再评估率
     *
     * 基本公式
     * (统计时间段内入院评估为中/高危并在出院进行再评估的患者人数) / (统计时间段内入院评估为中/高危的患者人数)
     *
     * 全部
     * 	分子：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区，初次（风险评估时机为新入的第一次）VTE风险评估分层为中高危且进行出院再评估（风险评估时机为出院，如果评估多次，计一次）的患者人数。
     * 	分母：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区，初次（风险评估时机为新入的第一次）VTE风险评估分层为中高危的患者人数。
     *
     * 中危
     * 	分子：出院时间在统计时间段内，出院科室为选择病区，初次（风险评估时机为新入的第一次）VTE风险评估分层为中危且进行出院再评估（风险评估时机为出院，如果评估多次，计一次）的患者人数。
     * 	分母：出院时间在统计时间段内，出院科室为选择病区，初次（风险评估时机为新入的第一次）VTE风险评估分层为中危的患者人数。
     *
     * 高危
     * 	分子：出院时间在统计时间段内，出院科室为选择病区，初次（风险评估时机为新入的第一次）VTE风险评估分层为高危且进行出院再评估（风险评估时机为出院，如果评估多次，计一次）的患者人数。
     * 	分母：出院时间在统计时间段内，出院科室为选择病区，初次（风险评估时机为新入的第一次）VTE风险评估分层为高危的患者人数。
     *
     * @param deptSn    科室/病区ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeType  时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result riskVteDischargeDiagnosis(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        Integer[] middleHigh = {2, 3};//高危，中危
        Integer[] middle = {3};//中危
        Integer[] highRank = {2};//高危
        Integer[] allPte = {1, 2, 3};//
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 全部(中高危)
            int firstSumMiddleHigh = vtePreventiveMapper.getSumByFirstRiskVtePreventiveRank(departments, item.getStartTime(), item.getEndTime(), 0, middleHigh, allPte).intValue();
            int firstSumMiddleHighDischarge = vtePreventiveMapper.getSumByFirstRiskVtePreventiveRankReVte(departments, item.getStartTime(), item.getEndTime(), 0, middleHigh, allPte).intValue();
            // 中危
            int firstSumMiddle = vtePreventiveMapper.getSumByFirstRiskVtePreventiveRank(departments, item.getStartTime(), item.getEndTime(), 0, middle, allPte).intValue();
            int firstSumMiddleDischarge = vtePreventiveMapper.getSumByFirstRiskVtePreventiveRankReVte(departments, item.getStartTime(), item.getEndTime(), 0, middle, allPte).intValue();
            // 高危
            int firstSumMHigh = vtePreventiveMapper.getSumByFirstRiskVtePreventiveRank(departments, item.getStartTime(), item.getEndTime(), 0, highRank, allPte).intValue();
            int firstSumHighDischarge = vtePreventiveMapper.getSumByFirstRiskVtePreventiveRankReVte(departments, item.getStartTime(), item.getEndTime(), 0, highRank, allPte).intValue();
            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allVtePatient", firstSumMiddleHigh == 0 ? "0%" : df.format((firstSumMiddleHighDischarge * 100.0F / firstSumMiddleHigh)) + "%");
            report.put("middle", firstSumMiddle == 0 ? "0%" : df.format((firstSumMiddleDischarge * 100.0F / firstSumMiddle)) + "%");
            report.put("height", firstSumMHigh == 0 ? "0%" : df.format((firstSumHighDischarge * 100.0F / firstSumMHigh)) + "%");
            report.put("firstSumMiddleHigh", Convert.toStr(firstSumMiddleHigh));
            report.put("firstSumMiddleHighDischarge", Convert.toStr(firstSumMiddleHighDischarge));
            report.put("firstSumMiddle", Convert.toStr(firstSumMiddle));
            report.put("firstSumMiddDischarge", Convert.toStr(firstSumMiddleDischarge));
            report.put("firstSumMHigh", Convert.toStr(firstSumMHigh));
            report.put("firstSumHighDischarge", Convert.toStr(firstSumHighDischarge));
            list.add(report);
        }
        return Result.success(list);
    }

    /**
     * 预防措施实施指标---内科【高危】患者预防比例
     *
     * 基本公式
     * (统计时间段内Padua VTE风险评估为高危并且采取物理/药物措施的患者人数) / (统计时间段内Padua VTE风险评估为高危)
     *
     * 全部
     * 	分子：评估时间在统计时间段内，风险评估类型为Padua，评估结果为高危(同一个病人如果有多次，计一次)，并且病人的有效防治医嘱（包含未停止和停止医嘱，不含作废医嘱）不为空的患者人数。
     * 	分母：评估时间在统计时间段内，风险评估类型为Padua，评估结果为高危(同一个病人如果有多次，计一次)的患者人数。
     *
     * 机械
     * 	分子：评估时间在统计时间段内，风险评估类型为Padua，评估结果为高危(同一个病人如果有多次，计一次)，并且病人的有效防治医嘱（包含未停止和停止医嘱，不含作废医嘱）包含机械预防措施的患者人数。
     *
     * 药物
     * 	分子：评估时间在统计时间段内，风险评估类型为Padua，评估结果为高危(同一个病人如果有多次，计一次)，并且病人的有效防治医嘱（包含未停止和停止医嘱，不含作废医嘱）包含药物预防措施的患者人数。
     *
     * @param deptSn    科室/病区ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeType  时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result preventHighInnerPatient(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        Integer[] preventiveRiskRank = {PreventiveRiskRankEnum.PADUA_GAO_WEI.getValue()};//高危
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 内科【高危】- 分母
            int sumPreventiveFenMu = vtePreventiveMapper.getSumByVtePreventive(departments, item.getStartTime(), item.getEndTime(), PreventiveTypeEnum.PADUA.getValue(), preventiveRiskRank, 0, 0, 0).intValue();

            // 内科【高危】- 全部(物理+机械)
            int sumPreventiveIsPreventionFenZi = vtePreventiveMapper.getSumByVtePreventiveAndDoctorAdvice(departments, item.getStartTime(), item.getEndTime(), PreventiveTypeEnum.PADUA.getValue(), preventiveRiskRank, 1, 0, 0).intValue();

            // 内科【高危】- 药物
            int drugSumPreventiveFenZi = vtePreventiveMapper.getSumByVtePreventiveAndDoctorAdvice(departments, item.getStartTime(), item.getEndTime(), PreventiveTypeEnum.PADUA.getValue(), preventiveRiskRank, 1, 1, 0).intValue();

            // 内科【高危】- 机械(物理)
            int physicalSumPreventive = vtePreventiveMapper.getSumByVtePreventiveAndDoctorAdvice(departments, item.getStartTime(), item.getEndTime(), PreventiveTypeEnum.PADUA.getValue(), preventiveRiskRank, 1, 0, 1).intValue();
            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allPrevention", sumPreventiveFenMu == 0 ? "0%" : df.format((sumPreventiveIsPreventionFenZi * 100.0F / sumPreventiveFenMu)) + "%");
            report.put("paduaPhysical", sumPreventiveFenMu == 0 ? "0%" : df.format((physicalSumPreventive * 100.0F / sumPreventiveFenMu)) + "%");
            report.put("drug", sumPreventiveFenMu == 0 ? "0%" : df.format((drugSumPreventiveFenZi * 100.0F / sumPreventiveFenMu)) + "%");
            report.put("allPreventionNumber", Convert.toStr(sumPreventiveFenMu));
            report.put("paduaPhysicalNumber", Convert.toStr(physicalSumPreventive));
            report.put("IsSumPreventionNumber", Convert.toStr(sumPreventiveIsPreventionFenZi));
            report.put("drugNumber", Convert.toStr(drugSumPreventiveFenZi));
            list.add(report);
        }
        return Result.success(list);
    }

    /**
     * 预防措施实施指标---外科【中/高】危患者的预防比例
     *
     * 基本公式
     * (统计时间段内Caprini VTE风险评估为中/高危并且采取物理/药物措施的患者人数) / (统计时间段内Caprini  VTE风险评估为高危)
     *
     * 全部
     * 	分子：评估时间在统计时间段内，风险评估类型为Caprini，评估结果为中/高危(同一个病人如果有多次，计一次)，并且病人的有效防治医嘱（包含未停止和停止医嘱，不含作废医嘱）不为空的患者人数。
     * 	分母：评估时间在统计时间段内，风险评估类型为Caprini，评估结果为中/高危(同一个病人如果有多次，计一次)的患者人数。
     *
     * 机械
     * 	分子：评估时间在统计时间段内，风险评估类型为Caprini，评估结果为中/高危(同一个病人如果有多次，计一次)，并且病人的有效防治医嘱（包含未停止和停止医嘱，不含作废医嘱）包含机械预防措施的患者人数。
     *
     * 药物
     * 	分子：评估时间在统计时间段内，风险评估类型为Caprini，评估结果为中/高危(同一个病人如果有多次，计一次)，并且病人的有效防治医嘱（包含未停止和停止医嘱，不含作废医嘱）包含药物预防措施的患者人数。
     *
     * @param deptSn    科室/病区ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeType  时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result preventMiddleAndHighOuterPatient(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        Integer[] preventiveRiskRank = {PreventiveRiskRankEnum.CAPRINI_ZHONG_WEI.getValue(), PreventiveRiskRankEnum.CAPRINI_GAO_WEI.getValue()};
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 外科【中/高】- 分母
            int sumPreventiveFenMu = vtePreventiveMapper.getSumByVtePreventive(departments, item.getStartTime(), item.getEndTime(), PreventiveTypeEnum.CAPRINI.getValue(), preventiveRiskRank, 0, 0, 0).intValue();

            // 外科【中/高】- 全部(物理预防+机械预防+有效放置医嘱)
            int sumPreventiveIsPreventionFenZi = vtePreventiveMapper.getSumByVtePreventiveAndDoctorAdvice(departments, item.getStartTime(), item.getEndTime(), PreventiveTypeEnum.CAPRINI.getValue(), preventiveRiskRank, 1, 0, 0).intValue();

            // 外科【中/高】- 药物预防+有效放置医嘱
            int drugSumPreventiveFenZi = vtePreventiveMapper.getSumByVtePreventiveAndDoctorAdvice(departments, item.getStartTime(), item.getEndTime(), PreventiveTypeEnum.CAPRINI.getValue(), preventiveRiskRank, 1, 1, 0).intValue();

            // 外科【中/高】- 机械预防(物理预防+有效放置医嘱)
            int physicalSumPreventiveFenZi = vtePreventiveMapper.getSumByVtePreventiveAndDoctorAdvice(departments, item.getStartTime(), item.getEndTime(), PreventiveTypeEnum.CAPRINI.getValue(), preventiveRiskRank, 1, 0, 1).intValue();
            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allPrevention", sumPreventiveFenMu == 0 ? "0%" : df.format((sumPreventiveIsPreventionFenZi * 100.0F / sumPreventiveFenMu)) + "%");
            report.put("paduaPhysical", sumPreventiveFenMu == 0 ? "0%" : df.format((physicalSumPreventiveFenZi * 100.0F / sumPreventiveFenMu)) + "%");
            report.put("drug", sumPreventiveFenMu == 0 ? "0%" : df.format((drugSumPreventiveFenZi * 100.0F / sumPreventiveFenMu)) + "%");
            report.put("sumPreventive", Convert.toStr(sumPreventiveIsPreventionFenZi));
            report.put("physicalSumPreventive", Convert.toStr(physicalSumPreventiveFenZi));
            report.put("sumPreventiveIsPrevention", Convert.toStr(sumPreventiveIsPreventionFenZi));
            report.put("drupSumPreventive", Convert.toStr(drugSumPreventiveFenZi));
            list.add(report);
        }
        return Result.success(list);
    }

    /**
     * 结局相关指标---医院内非预期死亡发生率
     *
     * 基本公式
     * 统计时间段出院的并且为非预期死亡的患者人数 / 统计时间段出院的患者人数
     *
     *  全部
     * 	分子：出院时间在统计时间段内，出院科室为选择病区，非预期死亡为是的患者人数。
     * 	分母：出院时间在统计时间段内，出院科室为选择病区的患者人数。
     *
     *  内科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区（科室类型为内科），非预期死亡为是的患者人数。
     * 	分母：出院时间在统计时间段内，出院科室为选择病区（科室类型为内科）的患者人数
     *
     *  外科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区，科室类型为外科，非预期死亡为是的患者人数。
     * 	分母：出院时间在统计时间段内，出院科室为选择病区（科室类型为外科）的患者人数。
     *
     * @param deptSn    科室/病区ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeType  时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result endingUnanticipatedDeath(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 全部
            int allSumFenMu = summaryMapper.getSumByPatientDischarge(departments, null, item.getStartTime(), item.getEndTime(), null, 0, 0).intValue();
            int allUnExpectedDeathSumFenZi = summaryMapper.getSumByPatientDischarge(departments, null, item.getStartTime(), item.getEndTime(), null, 1, 0).intValue();

            // 内科
            int inDeathSumFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), null, 0, 0).intValue();
            int inUnExpectedDeathSumFenZi = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), null, 1, 0).intValue();

            // 外科
            int outDeathSumFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), null, 0, 0).intValue();
            int outUnExpectedDeathSumFenZi = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), null, 1, 0).intValue();

            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allDeath", allSumFenMu == 0 ? "0%" : df.format((allUnExpectedDeathSumFenZi * 100.0F / allSumFenMu)) + "%");
            report.put("insideDeath", inDeathSumFenMu == 0 ? "0%" : df.format((inUnExpectedDeathSumFenZi * 100.0F / inDeathSumFenMu)) + "%");
            report.put("outerDeath", outDeathSumFenMu == 0 ? "0%" : df.format((outUnExpectedDeathSumFenZi * 100.0F / outDeathSumFenMu)) + "%");
            report.put("deathSum", Convert.toStr(allSumFenMu));
            report.put("deathPteSum", Convert.toStr(allUnExpectedDeathSumFenZi));
            report.put("inPtvDeathSum", Convert.toStr(inUnExpectedDeathSumFenZi));
            report.put("outDeathSum", Convert.toStr(outDeathSumFenMu));
            report.put("outPtvDeathSum", Convert.toStr(outUnExpectedDeathSumFenZi));
            list.add(report);
        }
        return Result.success(list);
    }

    /**
     * 结局相关指标---医院内PTE死亡发生率
     *
     * 基本公式
     * 统计时间段出院转归为死亡并且诊断PTE的患者数量/统计时间段出院的人数
     *
     * 全部
     * 	分子：出院时间在统计时间段内，出院科室为选择病区，出院类型为死亡，肺血栓栓塞症为是的病人数量。
     * 	分母：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区的患者人数。
     *
     * 内科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区（病区类型为内科），出院类型为死亡，肺血栓栓塞症为是的病人数量。
     * 	分母：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区（病区类型为内科）的患者人数。
     *
     * 外科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区（病区类型为外科），出院类型为死亡，肺血栓栓塞症为是的病人数量。
     * 	分母：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区（病区类型为外科）的患者人数。
     *
     * @param deptSn        科室/病区ID
     * @param startTime     开始时间
     * @param endTime       结束时间
     * @param timeType      时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result endingUnanticipatedDeathPie(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        Integer[] diePte = {3};// 3.死亡
        Integer[] allPte = {1, 2, 3}; // 1.医嘱出院 2.非医嘱出院 3.死亡
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 全部
            int allSumFenMu = summaryMapper.getSumByPatientDischarge(departments, null, item.getStartTime(), item.getEndTime(), allPte, 0, 0).intValue();
            int allPteDeathSumFenZi = summaryMapper.getSumByPatientDischarge(departments, null, item.getStartTime(), item.getEndTime(), diePte, 0, 1).intValue();

            // 内科
            int inDeathSumFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), allPte, 0, 0).intValue();
            int inPtvDeathSumFenZi = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), diePte, 0, 1).intValue();

            // 外科
            int outDeathSumFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), allPte, 0, 0).intValue();
            int outPtvDeathSumFenZi = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), diePte, 0, 1).intValue();

            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allDeath", allSumFenMu == 0 ? "0%" : df.format((allPteDeathSumFenZi * 100.0F / allSumFenMu)) + "%");
            report.put("insideDeath", inDeathSumFenMu == 0 ? "0%" : df.format((inPtvDeathSumFenZi * 100.0F / inDeathSumFenMu)) + "%");
            report.put("outerDeath", outDeathSumFenMu == 0 ? "0%" : df.format((outPtvDeathSumFenZi * 100.0F / outDeathSumFenMu)) + "%");
            report.put("deathSum", Convert.toStr(allSumFenMu));
            report.put("deathPteSum", Convert.toStr(allPteDeathSumFenZi));
            report.put("inPtvDeathSum", Convert.toStr(inPtvDeathSumFenZi));
            report.put("outDeathSum", Convert.toStr(outDeathSumFenMu));
            report.put("outPtvDeathSum", Convert.toStr(outPtvDeathSumFenZi));
            list.add(report);
        }
        return Result.success(list);
    }

    /**
     * 结局相关指标---PTE导致死亡占死亡总数比率
     *
     * 基本公式
     * 统计时间段出院转归为死亡并且诊断PTE的人数 / 统计时间段出院转归为死亡的人数
     *
     * 全部
     * 	分子：出院时间在统计时间段内，出院科室为选择病区，出院类型为死亡，肺血栓栓塞症为是的病人数量。
     * 	分母：出院时间在统计时间段内，出院科室为选择病区，出院类型为死亡的患者人数。
     *
     * 内科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区（科室类型为内科），出院类型为死亡，肺血栓栓塞症为是的病人数量。
     * 	分母：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区（科室类型为内科），出院类型为死亡的患者人数。
     *
     * 外科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区（科室类型为外科），出院类型为死亡，肺血栓栓塞症为是的病人数量。
     * 	分母：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区（科室类型为外科），出院类型为死亡的患者人数。
     *
     * @param deptSn    科室/病区ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeType  时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result endingDeathPieContrastSum(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        Integer[] death = {3};//3.死亡
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 全部
            int allFenMu = summaryMapper.getSumByPatientDischarge(departments, null, item.getStartTime(), item.getEndTime(), death, 0, 0).intValue();
            int allFenZi = summaryMapper.getSumByPatientDischarge(departments, null, item.getStartTime(), item.getEndTime(), death, 0, 1).intValue();

            // 内科
            int inFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), death, 0, 0).intValue();
            int inFenZi = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), death, 0, 1).intValue();

            // 外科
            int outFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), death, 0, 0).intValue();
            int outFenZi = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), death, 0, 1);

            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allDeath", allFenMu == 0 ? "0%" : df.format((allFenZi * 100.0F / allFenMu)) + "%");
            report.put("insideDeath", inFenMu == 0 ? "0%" : df.format((inFenZi * 100.0F / inFenMu)) + "%");
            report.put("outerDeath", outFenMu == 0 ? "0%" : df.format((outFenZi * 100.0F / outFenMu)) + "%");
            report.put("deathSum", Convert.toStr(allFenMu));
            report.put("deathPteSum", Convert.toStr(allFenZi));
            report.put("inPtvDeathSum", Convert.toStr(inFenZi));
            report.put("outDeathSum", Convert.toStr(outFenMu));
            report.put("outPtvDeathSum", Convert.toStr(outFenZi));
            list.add(report);
        }
        return Result.success(list);
    }

    /**
     * 结局相关指标---PTE死亡患者中未预防的比例
     *
     * 计算公式
     * 统计时间段出院转归为死亡、诊断PTE【并且未预防】的患者人数 / 统计时间段出院转归为死亡、诊断PTE 的患者人数
     *
     * 全部
     * 	分子：出院时间在统计时间段内，出院科室为选择病区，出院类型为死亡，肺血栓栓塞症为是，并且有效预防医嘱（不包含作废医嘱）为空的病人数量。
     * 	分母：出院时间在统计时间段内，出院科室为选择病区，出院类型为死亡，肺血栓栓塞症为是的患者人数。
     *
     * 内科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区（科室类型为内科），出院类型为死亡，肺血栓栓塞症为是，并且有效预防医嘱（不包含作废医嘱）为空的病人数量。
     * 	分母：出院时间在统计时间段内，出院科室为选择病区（科室类型为内科），出院类型为死亡，肺血栓栓塞症为是的患者人数。
     *
     * 外科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区（科室类型为外科），出院类型为死亡，肺血栓栓塞症为是，并且有效预防医嘱（不包含作废医嘱）为空的病人数量。
     * 	分母：出院时间在统计时间段内，出院科室为选择病区（科室类型为外科），出院类型为死亡，肺血栓栓塞症为是的患者人数。
     *
     * @param deptSn    科室/病区ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeType  时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result endingDeathPieNoPreventSum(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        Integer[] death = {3};// 3、死亡
        List<Map<String, String>> list = new ArrayList<>();
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 全部
            int allFenMu = summaryMapper.getSumByPatientDischarge(departments, null, item.getStartTime(), item.getEndTime(), death, 0, 1).intValue();
            List<Integer> targetPatientIds = summaryMapper.getSumByPatientDischargeAndDoctorAdvice(departments, null, item.getStartTime(), item.getEndTime(), death, 0, 1);
            Integer unYuFangCount = doctorAdviceMapper.selectByPatients(targetPatientIds);
            int allFenZi = targetPatientIds.size() - unYuFangCount.intValue();

            // 内科
            int inFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), death, 0, 1).intValue();
            List<Integer> inPtvDeathPatientIds = summaryMapper.getSumByPatientDischargeAndDoctorAdvice(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), death, 0, 1);
            Integer inUnYuFangCount = doctorAdviceMapper.selectByPatients(inPtvDeathPatientIds);
            int inFenZi = inPtvDeathPatientIds.size() - inUnYuFangCount.intValue();

            // 外科
            int outFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), death, 0, 1).intValue();
            List<Integer> outPtvDeathPatientIds = summaryMapper.getSumByPatientDischargeAndDoctorAdvice(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), death, 0, 1);
            Integer outUnYuFangCount = doctorAdviceMapper.selectByPatients(outPtvDeathPatientIds);
            int outFenZi = outPtvDeathPatientIds.size() - outUnYuFangCount.intValue();

            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allDeath", allFenMu == 0 ? "0%" : df.format((allFenZi * 100.0F / allFenMu)) + "%");
            report.put("insideDeath", inFenMu == 0 ? "0%" : df.format((inFenZi * 100.0F / inFenMu)) + "%");
            report.put("outerDeath", outFenMu == 0 ? "0%" : df.format((outFenZi * 100.0F / outFenMu)) + "%");
            report.put("deathSum", Convert.toStr(allFenMu));
            report.put("deathPteSum", Convert.toStr(allFenZi));
            report.put("inPtvDeathSum", Convert.toStr(inFenZi));
            report.put("outDeathSum", Convert.toStr(outFenMu));
            report.put("outPtvDeathSum", Convert.toStr(outFenZi));
            list.add(report);
        }
        return Result.success(list);
    }

    /**
     * 诊治相关指标---PTE诊断成功率
     *
     * 计算公式
     * (统计时间段内出院病人，诊断PTE，没有死亡的患者人数) / (统计时间段出院病人，诊断PTE的患者人数)
     *
     * 全部
     * 	分子：出院时间在统计时间段内，出院科室为选择病区，出院类型为医嘱出院、非医嘱出院，肺血栓栓塞症为是的病人数量。
     * 	分母：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区，肺血栓栓塞症为是的病人数量。
     *
     * 内科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区（科室类型为内科），出院类型为医嘱出院、非医嘱出院，肺血栓栓塞症为是的病人数量。
     * 	分母：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区（科室类型为内科），肺血栓栓塞症为是的病人数量。
     *
     * 外科
     * 	分子：出院时间在统计时间段内，出院科室为选择病区（科室类型为外科），出院类型为医嘱出院、非医嘱出院，肺血栓栓塞症为是的病人数量。
     * 	分母：出院时间在统计时间段内，出院转归不为其他，出院科室为选择病区（科室类型为外科），肺血栓栓塞症为是的病人数量。
     *
     * @param deptSn    科室/病区ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param timeType  时间类型 1.月度 2.季度 3.年度
     * @return
     */
    @Override
    public Result endingPieSuccess(String deptSn, String startTime, String endTime, Integer timeType) {
        List<Integer> departments = getDepartments(deptSn);
        Integer[] allPte = {1, 2, 3};//1、医嘱出院 2、非医嘱出院 3、死亡
        Integer[] okPte = {1, 2};//1、医嘱出院 2、非医嘱出院
        List<Map<String, String>> list = new ArrayList<>();
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, timeType)) {
            // 全部
            int allPieSuccessNumFenMu = summaryMapper.getSumByPatientDischarge(departments, null, item.getStartTime(), item.getEndTime(), allPte, 0, 1).intValue();
            int allPieSuccessNumFenZi = summaryMapper.getSumByPatientDischarge(departments, null, item.getStartTime(), item.getEndTime(), okPte, 0, 1).intValue();

            // 内科
            int inPieSuccessNumFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), allPte, 0, 1).intValue();
            int inPieSuccessNumFenZi = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.PADUA.getValue(), item.getStartTime(), item.getEndTime(), okPte, 0, 1).intValue();

            // 外科
            int outPieSuccessNumFenMu = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), allPte, 0, 1).intValue();
            int outPieSuccessNumFenZi = summaryMapper.getSumByPatientDischarge(departments, DeptTypeEnum.CAPRINI.getValue(), item.getStartTime(), item.getEndTime(), okPte, 0, 1).intValue();

            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("allDeath", allPieSuccessNumFenZi == 0 ? "0%" : df.format((allPieSuccessNumFenZi * 100.0F / allPieSuccessNumFenMu)) + "%");
            report.put("insideDeath", inPieSuccessNumFenZi == 0 ? "0%" : df.format((inPieSuccessNumFenZi * 100.0F / inPieSuccessNumFenMu)) + "%");
            report.put("outerDeath", outPieSuccessNumFenZi == 0 ? "0%" : df.format((outPieSuccessNumFenZi * 100.0F / outPieSuccessNumFenMu)) + "%");
            report.put("deathSum", Convert.toStr(allPieSuccessNumFenMu));
            report.put("deathPteSum", Convert.toStr(allPieSuccessNumFenZi));
            report.put("inPtvDeathSum", Convert.toStr(inPieSuccessNumFenZi));
            report.put("outDeathSum", Convert.toStr(outPieSuccessNumFenMu));
            report.put("outPtvDeathSum", Convert.toStr(outPieSuccessNumFenZi));
            list.add(report);
        }
        return Result.success(list);
    }

    @Override
    public Result vtePreventionAdviceRate(String deptSn, String startTime, String endTime) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, 1)) {
            Map<String, String> report = new HashMap<>();
            Integer patientSum = patientTransitionMapper.getDurationPatientSum(departments, item.getStartTime(), item.getEndTime());
            if (patientSum == null) {
                patientSum = 0;
            }
            Integer vteSum = doctorAdviceMapper.getDoctorAdviceDurationSumByDeptSn(departments, item.getStartTime(), item.getEndTime());
            if (vteSum == null) {
                vteSum = 0;
            }
            report.put("monthTime", item.getDateTime());
            report.put("vteRate", patientSum == 0 ? "0%" : df.format((vteSum * 100.0F / patientSum)) + "%");
            report.put("vteSum", Convert.toStr(Integer.valueOf(vteSum)));
            report.put("patientSum", Convert.toStr(patientSum));
            list.add(report);
        }
        return Result.success(list);
    }

    @Override
    public Result dvtPreventionAdviceRate(String deptSn, String startTime, String endTime) {
        List<Integer> departments = getDepartments(deptSn);
        List<Map<String, String>> list = new ArrayList<>();
        for (QualityControlDatePO item : getDateTimes(startTime, endTime, 1)) {
            Integer patientSum = patientTransitionMapper.getDurationPatientSum(departments, item.getStartTime(), item.getEndTime());
            if (patientSum == null) {
                patientSum = 0;
            }
            Integer dvtSum = dvtDiagnoseMapper.getDurationDvtSumByDeptSn(departments, item.getStartTime(), item.getEndTime());
            if (dvtSum == null) {
                dvtSum = 0;
            }
            Map<String, String> report = new HashMap<>();
            report.put("monthTime", item.getDateTime());
            report.put("vteRate", patientSum == 0 ? "0%" : df.format((dvtSum * 100.0F / patientSum)) + "%");
            report.put("dvtSum", Convert.toStr(dvtSum));
            report.put("patientSum", Convert.toStr(patientSum));
            list.add(report);

        }
        return Result.success(list);
    }

    private List<Integer> getDepartments(String deptSn) {
        List<Integer> departments;
        if (StrUtil.isEmpty(deptSn)) {
            departments = departmentMapper.getAllDeptSn();
        } else {
            departments = Arrays.stream(deptSn.split(",")).map(Integer::valueOf).collect(Collectors.toList());
        }
        return departments;
    }

    public List<QualityControlDatePO> getDateTimes(String startTimeStr, String endTimeStr, Integer timeType) {
        DateTime startTime = DateUtil.parse(startTimeStr, "yyyy-MM");
        DateTime endTime = DateUtil.parse(endTimeStr, "yyyy-MM");
        List<QualityControlDatePO> dateTimes = new ArrayList<>();
        if (timeType == QualityControlTypeEnum.MONTH_CONTROL.getValue()) {//月度
            dateTimes = DateUtil.rangeToList(startTime, endTime, DateField.MONTH).stream().map(item -> {
                DateTime monthStartTime = DateUtil.beginOfMonth(item);//当前月开始时间
                DateTime monthEndTime = DateUtil.endOfMonth(item);//当前月结束时间
//                if (startTime.getTime() > monthStartTime.getTime()) {
//                    monthStartTime = startTime;
//                }
//                if (endTime.getTime() < monthEndTime.getTime()) {
//                    monthEndTime = DateUtil.endOfDay(endTime);
//                }
                return new QualityControlDatePO(DateUtil.format(item, "yyyy-MM"), monthStartTime, monthEndTime);
            }).collect(Collectors.toList());
        } else if (timeType == QualityControlTypeEnum.QUARTER_CONTROL.getValue()) {//季度
            dateTimes = DateUtil.yearAndQuarter(startTime, endTime).stream().map(item -> {
                String key = item.substring(0, 4) + "Q" + item.substring(4, 5);
                item = item.substring(0, 4) + "-0" + (Integer.parseInt(item.substring(4, 5)) * 3);
                DateTime dateTime = DateUtil.parse(item, "yyyy-MM");
                DateTime quarterStartTime = DateUtil.beginOfQuarter(dateTime);
//                if (startTime.getTime() > quarterStartTime.getTime()) {
//                    quarterStartTime = startTime;
//                }
                DateTime quarterEndTime = DateUtil.endOfQuarter(dateTime);
//                if (endTime.getTime() < quarterEndTime.getTime()) {
//                    quarterEndTime = endTime;
//                }
                return new QualityControlDatePO(key, quarterStartTime, quarterEndTime);
            }).collect(Collectors.toList());
        } else if (timeType == QualityControlTypeEnum.YEAR_CONTROL.getValue()) {//年度
            dateTimes = DateUtil.rangeToList(startTime, endTime, DateField.YEAR).stream().map(item -> {
                DateTime yearStartTime = DateUtil.beginOfYear(item);//年开始时间
                DateTime yearEndTime = DateUtil.endOfYear(item);//年结束时间
//                if (yearStartTime.getTime() < startTime.getTime()) {
//                    yearStartTime = startTime;
//                }
//                if (yearEndTime.getTime() > endTime.getTime()) {
//                    yearEndTime = DateUtil.endOfDay(endTime);
//                }
                return new QualityControlDatePO(DateUtil.format(item, "yyyy"), yearStartTime, yearEndTime);
            }).collect(Collectors.toList());
        }
        return dateTimes;
    }

}
